package extend.db.entity;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * 实体反射工具
 * <B>说明：</B>
 * <pre>
 *  用于换成实体类字段
 * </pre>
 * <B>示例：</B>
 * <pre>
 *  略
 * </pre>
 * <B>日志：</B>
 * <pre>
 *  略
 * </pre>
 * <B>注意事项：</B>
 * <pre>
 *  略
 * </pre>
 */
public class EntityReflectUtil
{

    /**
     * 字段定义缓存列表
     *<B>说明：</B>
     *<pre>
     * 通过反射获取Field对象后缓存于此
     *</pre>
     */
    private static final Map<Class<?>,Map<String,Field>> declaredFieldsCache =
            new HashMap<>();

    /**
     * 获取对象属性
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @param target 目标对象
     */
    public static Map<String,Object> getAttrs(Object target)
    {
        return getAttrs(target,false);
    }

    /**
     * 获取对象属性
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @param target 目标对象
     * @param excludeNull 是否排除null 属性
     */
    public static Map<String,Object> getAttrs(Object target,boolean excludeNull)
    {
        Class targetClazz = target.getClass();
        Map<String,Field> fields = getFields(targetClazz);
        if (fields.size() == 0) {
            return null;
        }

        Map<String,Object> attrs = new HashMap<>();
        Field field;
        for (Map.Entry<String, Field> fieldSet : fields.entrySet()) {
            try {
                field = fieldSet.getValue();
                field.setAccessible(true);
                if (excludeNull == true) {
                    if (field != null) {
                        attrs.put(fieldSet.getKey(),field.get(target));
                    }
                } else {
                    attrs.put(fieldSet.getKey(),field.get(target));
                }

            } catch (Exception e) {
                // 不做任何事情
            }
        }

        return attrs;
    }

    public static Map<String,Object> getAttrs(Object target,String[] fieldsName)
    {
        return getAttrs(target,fieldsName,false);
    }

    /**
     * 获取对象属性
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @param target 目标对象
     * @param excludeNull 是否排除null 属性
     */
    public static Map<String,Object> getAttrs(Object target,String[] fieldsName,boolean excludeNull)
    {
        Class targetClazz = target.getClass();
        Map<String,Field> fields = getFields(targetClazz);
        if (fields.size() == 0) {
            return null;
        }

        Map<String,Object> attrs = new HashMap<>();
        Field field;

        for (String fieldName:fieldsName) {
            try {
                if (fields.containsKey(fieldName)) {
                    field = fields.get(fieldName);
                    field.setAccessible(true);
                    if (excludeNull == true) {
                        if (field != null) {
                            attrs.put(fieldName,field.get(target));
                        }
                    } else {
                        attrs.put(fieldName,field.get(target));
                    }
                }
            } catch (Exception ex) {

            }
        }

        return attrs;
    }



    /**
     * 设置对象属性值
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @param target 属性名
     * @param attrs 对象属性列表
     */
    public static void setAttrs(Object target,Map<String,Object> attrs)
    {
        Class targetClazz = target.getClass();
        String fieldName;
        Field field;
        Map<String,Field> fields = getFields(targetClazz);
        if (fields.size() == 0) {
            return;
        }

        for (Map.Entry<String, Object> attr : attrs.entrySet()) {
            try {
                fieldName = attr.getKey();
                if (fields.containsKey(fieldName)) {
                    field = fields.get(fieldName);
                    field.setAccessible(true);
                    field.set(target,attr.getValue());
                }
            } catch (Exception e) {
                // 不做任何事情
            }
        }
    }

    /**
     * 获取类全部字段
     *<B>说明：</B>
     *<pre>
     * 方法详细描述
     *</pre>
     */
    public static Map<String,Field> getFields(Class<?> clazz)
    {

        if (!declaredFieldsCache.containsKey(clazz)) {
            // 重新读取
            Map<String,Field> fields = getDeclaredFields(clazz);
            declaredFieldsCache.put(clazz,fields.size() > 0 ? fields : new HashMap());
        }

        return declaredFieldsCache.get(clazz);
    }

    /**
     * 获取类全部字段
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     * @return 未找道属性则，返回null
     */
    public static Map<String,Field> getDeclaredFields(Class<?> clazz)
    {
        Map<String,Field> clazzFields = new HashMap<>();

        Field[] fields = clazz.getDeclaredFields() ;
        for (Field field : fields) {
            clazzFields.put(field.getName(),field);
        }

        return clazzFields;
    }
}
